﻿Namespace Security
    Public Class KeyMaster
        Implements IDisposable

        Private Shared mAnonymous As New KeyMaster(-1)
        Public Shared Function Anonymous() As KeyMaster
            Return mAnonymous
        End Function
        Public Shared Function GetByBuddyId(ByVal buddyId As Integer) As KeyMaster
            Dim clsB As Entities.Buddy = Buddies.Handler.GetById(buddyId)
            If clsB Is Nothing Then
                Return mAnonymous
            Else
                Dim clsRet As New KeyMaster(buddyId)
                clsRet.SetGroupMemberShips(Handler.GetAllByBuddyId(buddyId))
                Return clsRet
            End If
        End Function

        Public ReadOnly BuddyId As Integer
        Friend Sub New(ByVal buddyId As Integer)
            Me.BuddyId = buddyId
            AddHandler Buddies.Manager.Updated, AddressOf EventHandler_BuddyUpdated
        End Sub
        Private Sub EventHandler_BuddyUpdated(ByVal buddy As Entities.Buddy)
            Try
                If BuddyId = buddy.Id Then SetGroupMemberShips(Handler.GetAllByBuddyId(buddy.Id))
            Catch ex As Exception
                mGroups.Clear()
                Framework.Misc.HandleException(ex)
            End Try
        End Sub

        Private mGroups As New Generic.HashSet(Of Integer)
        Private Sub SetGroupMemberShips(ByVal groups As Generic.List(Of Entities.SecurityGroup))
            Dim aTmp As New HashSet(Of Integer)
            For Each clsG As Entities.SecurityGroup In groups
                aTmp.Add(clsG.Id)
            Next
            mGroups = aTmp
        End Sub

        Public Delegate Function GroupDissolverDelegate(Of T)(ByVal [object] As T) As Generic.HashSet(Of Integer)
        Public Shared Sub RegisterDissolver(Of T)(ByVal callBack As GroupDissolverDelegate(Of T))
            Dim strKey As String = GetType(T).FullName
            mGroupDissolvers.Add(strKey, callBack)
        End Sub
        Private Shared mGroupDissolvers As New Generic.Dictionary(Of String, Object)

        Public Function IsGranted(ByVal securityGroupIds As HashSet(Of Integer)) As Boolean
            For Each iId As Integer In securityGroupIds
                If mGroups.Contains(iId) Then Return True
            Next
            Return False
        End Function

        Public Function IsGranted(Of T)(ByVal [object] As T) As Boolean
            Dim strKey As String = GetType(T).FullName
            Dim clsCallBack As GroupDissolverDelegate(Of T)
            clsCallBack = DirectCast(mGroupDissolvers(strKey), GroupDissolverDelegate(Of T))
            Dim aGroupIds As Generic.HashSet(Of Integer) = clsCallBack.Invoke([object])
            Return IsGranted(aGroupIds)
        End Function

        Private disposedValue As Boolean = False        ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                End If
                RemoveHandler Buddies.Manager.Updated, AddressOf EventHandler_BuddyUpdated
            End If
            Me.disposedValue = True
        End Sub

#Region " IDisposable Support "
        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
#End Region

    End Class
End Namespace